//1、头文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#define LED_ON _IO('L', 1)
#define LED_OFF _IO('L', 2)

#define LED_ALL_ON _IOW('L',1,int)
#define LED_ALL_OFF _IOW('L',2,int)

struct stm32mp157{
	unsigned int major;
	struct class *cls;
	struct device *dev;
	unsigned int *mod;
	unsigned int *odr;
};
struct stm32mp157 *drv_led;

int drv_led_open(struct inode *ide, struct file *filp)
{
	int ret =0;
	printk("---%s----\r\n",__FUNCTION__);
	return ret;
}
int drv_led_close(struct inode *ide, struct file *filp)
{
	int ret =0;
	printk("---%s----\r\n",__FUNCTION__);
	return ret;
}
ssize_t drv_led_write(struct file *fle, const char __user *buf, size_t size, loff_t *flag)
{
	ssize_t ret =0;
	unsigned int led_status=0;
	printk("---%s----\r\n",__FUNCTION__);
	
	ret = copy_from_user(&led_status, buf, size);
	if(ret !=0)
	{
		printk("copy_from_user_err\r\n");
		return ret;
	}
	if(led_status==0)
	{
		*drv_led->odr &= ~(0x01<<5);
	}
	else
	{
		*drv_led->odr |= 0x01<<5;
	}
	return ret;

}
long drv_led_ioctl(struct file *flp, unsigned int cmd , unsigned long buf)
{
	long ret =0;
	printk("---%s----\r\n",__FUNCTION__);
	switch(cmd)
	{
		case LED_ON:
			if(buf == 1)
			{
				*drv_led->odr |= 0x01<<5;	
			}
			if(buf == 2)
			{
				//第二个灯亮
			}
			if(buf == 3)
			{
				//第三个灯亮
			}
			break;
		case LED_OFF:
			if(buf == 1)
			{
				*drv_led->odr &= ~(0x01<<5);	
			}
			if(buf == 2)
			{
				//第二个灯灭
			}
			if(buf == 3)
			{
				//第三个灯灭
			}
			break;
		default :
			printk("cmd not spport\r\n");
			break;
	}
	return ret;

}

struct file_operations led_fops={
	.open = drv_led_open,
	.release = drv_led_close,
	.write = drv_led_write,
	.unlocked_ioctl = drv_led_ioctl,
};


//2、加载函数
static int __init drv_led_init(void)
{
	int ret =0;
	printk("---%s---\r\n",__FUNCTION__);
	//1、实例化对象
	drv_led = kzalloc(sizeof(struct stm32mp157), GFP_KERNEL);
	if(IS_ERR(drv_led))
	{
		printk("kzalloc_err\r\n");
		ret = PTR_ERR(drv_led);
		return ret;
	}
	//2、申请设备号
	drv_led->major = register_chrdev(0, "drv_led", &led_fops);
	if(drv_led->major<0)
	{
		printk("register_chrdev_err\r\n");
		ret = drv_led->major;
		goto register_chrdev_err;
	}
	//3、创建类
	drv_led->cls = class_create(THIS_MODULE, "drv_led");
	if(IS_ERR(drv_led->cls))
	{
		printk("class_create_err\r\n");
		ret = PTR_ERR(drv_led->cls);
		goto class_create_err;
	}
	//4、创建设备节点
	drv_led->dev = device_create(drv_led->cls, NULL, MKDEV(drv_led->major, 1), NULL, "drv_led");
	if(IS_ERR(drv_led->dev))
	{
		printk("device_create_err\r\n");
		ret = PTR_ERR(drv_led->dev);
		goto device_create_err;
	}

	//5、硬件初始化
	drv_led->mod = ioremap(0x54004000, 0x400);
	if(IS_ERR(drv_led->mod))
	{
		printk("ioremap_err\r\n");
		ret = PTR_ERR(drv_led->mod);
		goto ioremap_err;
	}
	drv_led->odr = drv_led->mod + 5;

	*drv_led->mod &= ~(0x03<<10);
	*drv_led->mod |= (0x01<<10);
	
	*drv_led->odr |= 0x01<<5;
	
	return ret;
ioremap_err:
	device_destroy(drv_led->cls, MKDEV(drv_led->major, 1));	
device_create_err:
	class_destroy(drv_led->cls);
class_create_err:
	unregister_chrdev(drv_led->major, "drv_led");
register_chrdev_err:
	kfree(drv_led);
	return ret;
}

//3、卸载函数
void __exit drv_led_exit(void)
{
	printk("---%s---\r\n",__FUNCTION__);
	iounmap(drv_led->mod);
	device_destroy(drv_led->cls, MKDEV(drv_led->major, 1));
	class_destroy(drv_led->cls);
	unregister_chrdev(drv_led->major, "drv_led");
	kfree(drv_led);
}

//4、模块声明与认证
module_init(drv_led_init);
module_exit(drv_led_exit);
MODULE_LICENSE("GPL");



